package com.hwd.gmall.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hwd.gmall.common.constant.ProductConst;
import com.hwd.gmall.model.product.*;
import com.hwd.gmall.product.mapper.*;
import com.hwd.gmall.product.service.ManageService;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;

/**
 * 后台管理页面使用的业务层实现类
 *
 * @author 黄伟东/Victor
 * @date 2022/4/18 18:43
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class ManageServiceImpl implements ManageService {

    @Resource
    private BaseCategory1Mapper baseCategory1Mapper;

    @Resource
    private BaseCategory2Mapper baseCategory2Mapper;

    @Resource
    private BaseCategory3Mapper baseCategory3Mapper;

    @Resource
    private BaseAttrInfoMapper baseAttrInfoMapper;

    @Resource
    private BaseAttrValueMapper baseAttrValueMapper;

    @Resource
    private BaseSaleAttrMapper baseSaleAttrMapper;

    @Resource
    private BaseTrademarkMapper baseTrademarkMapper;

    @Resource
    private SpuInfoMapper spuInfoMapper;

    @Resource
    private SpuImageMapper spuImageMapper;

    @Resource
    private SpuSaleAttrMapper spuSaleAttrMapper;

    @Resource
    private SpuSaleAttrValueMapper spuSaleAttrValueMapper;

    @Resource
    private SkuInfoMapper skuInfoMapper;

    @Resource
    private SkuImageMapper skuImageMapper;

    @Resource
    private SkuAttrValueMapper skuAttrValueMapper;

    @Resource
    private SkuSaleAttrValueMapper skuSaleAttrValueMapper;

    @Resource
    private RabbitTemplate rabbitTemplate;

    /**
     * 查询所有的一级分类
     *
     * @return java.util.List<com.hwd.gmall.model.product.BaseCategory1>
     */
    @Override
    public List<BaseCategory1> listCategory1s() {
        return baseCategory1Mapper.selectList(null);
    }

    /**
     * 根据一级分类id查询二级分类
     *
     * @param category1Id 一级分类id
     * @return java.util.List<com.hwd.gmall.model.product.BaseCategory2>
     */
    @Override
    public List<BaseCategory2> listCategory2ByCategory1Id(Long category1Id) {
        return baseCategory2Mapper.selectList(
                new LambdaQueryWrapper<BaseCategory2>()
                        .eq(BaseCategory2::getCategory1Id, category1Id));
    }

    /**
     * 根据二级分类id查询三级分类
     *
     * @param category2Id 二级分类id
     * @return java.util.List<com.hwd.gmall.model.product.BaseCategory3>
     */
    @Override
    public List<BaseCategory3> listCategory3ByCategory2Id(Long category2Id) {
        return baseCategory3Mapper.selectList(
                new LambdaQueryWrapper<BaseCategory3>()
                        .eq(BaseCategory3::getCategory2Id, category2Id));
    }

    /**
     * 保存平台属性
     *
     * @param baseAttrInfo 平台属性
     */
    @Override
    public void saveAttrInfo(BaseAttrInfo baseAttrInfo) {
        // 参数检验
        if (baseAttrInfo == null) {
            throw new RuntimeException("参数不能为空");
        }
        // 保存平台属性
        if (baseAttrInfo.getId() != null) {
            // 修改
            int update = baseAttrInfoMapper.updateById(baseAttrInfo);
            if (update < 0) {
                throw new RuntimeException("修改平台属性失败");
            }
            // 旧的全部删掉
            int delete = baseAttrValueMapper.delete(
                    new LambdaQueryWrapper<BaseAttrValue>()
                            .eq(BaseAttrValue::getAttrId, baseAttrInfo.getId()));
            if (delete < 0) {
                throw new RuntimeException("修改平台属性失败");
            }

        } else {
            // 新增
            int insert = baseAttrInfoMapper.insert(baseAttrInfo);
            if (insert <= 0) {
                throw new RuntimeException("新增平台属性值失败");
            }
        }

        // 获取平台属性名称自增id
        Long baseAttrInfoId = baseAttrInfo.getId();

        // 获取平台属性值
        List<BaseAttrValue> attrValueList = baseAttrInfo.getAttrValueList();

        // 保存平台属性值
        // 方案一：传统的for循环,串行化执行
        // 方案二：流式编程
        attrValueList.stream()
                .peek(baseAttrValue -> baseAttrValue.setAttrId(baseAttrInfoId))
                .forEach(baseAttrValue -> {
                    // 新增平台属性
                    int insert = baseAttrValueMapper.insert(baseAttrValue);
                    if (insert <= 0) {
                        throw new RuntimeException("新增平台属性值失败");
                    }
                });

    }

    /**
     * 根据分类id和分类的级别查询符合条件的平台属性列表
     *
     * @param category1Id 一级平台分类id
     * @param category2Id 二级平台分类id
     * @param category3Id 三级平台分类id
     * @return java.util.List<com.hwd.gmall.model.product.BaseAttrInfo>
     */
    @Override
    public List<BaseAttrInfo> listBaseAttrInfoByCategory(Long category1Id,
                                                         Long category2Id,
                                                         Long category3Id) {
        return baseAttrInfoMapper.selectBaseAttrInfoByCategory(category1Id, category2Id, category3Id);
    }

    /**
     * 根据平台属性名称id查询平台属性值列表
     *
     * @param attrId 平台属性名称id
     * @return java.util.List<com.hwd.gmall.model.product.BaseAttrValue>
     */
    @Override
    public List<BaseAttrValue> listAttrValueByAttrId(Long attrId) {
        return baseAttrValueMapper.selectList(
                new LambdaQueryWrapper<BaseAttrValue>()
                        .eq(BaseAttrValue::getAttrId, attrId));
    }

    /**
     * 查询所有品牌表信息
     *
     * @return java.util.List<com.hwd.gmall.model.product.BaseTrademark>
     */
    @Override
    public List<BaseTrademark> listBaseTrademarks() {
        return baseTrademarkMapper.selectList(null);
    }

    /**
     * 查询所有销售属性表信息
     *
     * @return java.util.List<com.hwd.gmall.model.product.BaseSaleAttr>
     */
    @Override
    public List<BaseSaleAttr> listBaseSaleAttrs() {
        return baseSaleAttrMapper.selectList(null);
    }

    /**
     * 保存spu的信息
     *
     * @param spuInfo spu的信息
     */
    @Override
    public void saveSpuInfo(SpuInfo spuInfo) {
        // 参数校验
        if (spuInfo == null) {
            throw new RuntimeException("参数不能为空");
        }
        // 判断是否有id，有 表示修改，无表示新增
        if (spuInfo.getId() != null) {
            // 修改spu基本信息
            int update = spuInfoMapper.updateById(spuInfo);
            if (update < 0) {
                throw new RuntimeException("修改spu失败");
            }

            // 删除spu附属表信息
            deleteSpuExtraInfo(spuInfo);
        } else {
            // 新增spu基本信息
            int insert = spuInfoMapper.insert(spuInfo);
            if (insert < 0) {
                throw new RuntimeException("新增spu失败");
            }
        }

        // 保存图片
        saveSpuImageList(spuInfo.getSpuImageList(), spuInfo.getId());

        // 新增销售属性和值表
        saveSpuSaleAttrList(spuInfo.getSpuSaleAttrList(), spuInfo.getId());

    }

    /**
     * 分页条件查询spu的信息
     *
     * @param page        当前页数
     * @param size        没有显示条数
     * @param category3Id 三级分类id
     * @return java.util.List<com.hwd.gmall.model.product.SpuInfo>
     */
    @Override
    public IPage<SpuInfo> listSpuInfo(Long page, Long size, Long category3Id) {
        return spuInfoMapper.selectPage(
                new Page<>(page, size),
                new LambdaQueryWrapper<SpuInfo>()
                        .eq(SpuInfo::getCategory3Id, category3Id));
    }

    /**
     * 根据spu的id查询spu的销售属性列表
     *
     * @param spuId spu的id
     * @return java.util.List<com.hwd.gmall.model.product.SpuSaleAttr>
     */
    @Override
    public List<SpuSaleAttr> listSpuSaleAttr(Long spuId) {
        return spuSaleAttrMapper.selectSpuSaleAttrBySpuId(spuId);
    }

    /**
     * 根据spu的id查询spu的图片
     *
     * @param spuId spu的id
     * @return java.util.List<com.hwd.gmall.model.product.SpuImage>
     */
    @Override
    public List<SpuImage> listSpuImage(Long spuId) {
        return spuImageMapper.selectList(
                new LambdaQueryWrapper<SpuImage>()
                        .eq(SpuImage::getSpuId, spuId));
    }

    /**
     * 保存sku的信息/修改sku的信息
     *
     * @param skuInfo sku信息
     */
    @Override
    public void saveSkuInfo(SkuInfo skuInfo) {
        // 参数校验
        if (skuInfo == null) {
            throw new RuntimeException("参数不能为空");
        }

        // 判断skuInfo的id是否为空
        if (skuInfo.getId() != null) {
            // id不为空，表示修改
            skuInfoMapper.updateById(skuInfo);

            // 删除旧的附属表信息
            deleteSkuExtraInfo(skuInfo);
        } else {
            // id为空，表示新增
            int insert = skuInfoMapper.insert(skuInfo);
            if (insert <= 0) {
                throw new RuntimeException("新增sku失败");
            }
        }

        // 新增sku的图片
        saveSkuImageList(skuInfo.getSkuImageList(), skuInfo.getId());

        // 新增sku的平台属性
        saveSkuAttrValueList(skuInfo.getSkuAttrValueList(), skuInfo.getId());

        // 新增sku销售属性
        saveSkuSaleAttrValueList(skuInfo.getSkuSaleAttrValueList(), skuInfo.getId(), skuInfo.getSpuId());

    }

    /**
     * 分页查询sku的信息
     *
     * @param page 当前页数
     * @param size 每页显示数量
     * @return com.baomidou.mybatisplus.core.metadata.IPage<com.hwd.gmall.model.product.SkuInfo>
     */
    @Override
    public IPage<SkuInfo> listSkuInfo(Long page, Long size) {
        return skuInfoMapper.selectPage(new Page<>(page, size), null);
    }

    /**
     * sku上架/下架
     *
     * @param skuId      sku的id
     * @param saleStatus sku是否销售，1：是  0：否
     */
    @Override
    public void onSaleOrCancelSal(Long skuId, Short saleStatus) {
        // 参数检验
        if (skuId == null) {
            throw new RuntimeException("参数错误");
        }

        // 查询数据库当前skuId是否存在
        SkuInfo skuInfo = skuInfoMapper.selectById(skuId);
        if (skuInfo == null || skuInfo.getId() == null) {
            throw new RuntimeException("商品不存在！");
        }

        // 修改销售状态
        skuInfo.setIsSale(saleStatus);
        int update = skuInfoMapper.updateById(skuInfo);
        // 幂等性校验
        if (update < 0) {
            throw new RuntimeException("上下架失败！");
        }

        // 同步数据到es中----存在数据一致性问题！
        if (saleStatus.equals(ProductConst.SKU_ON_SALE)) {
            // 上架，同步——>异步
            rabbitTemplate.convertAndSend(ProductConst.SKU_EXCHANGE, ProductConst.SKU_UPPER_ROUTING_KEY, skuId + "");
        } else {
            // 下架，同步——>异步
            rabbitTemplate.convertAndSend(ProductConst.SKU_EXCHANGE, ProductConst.SKU_DOWN_ROUTING_KEY, skuId + "");
        }

    }

    /**
     * 分页查询品牌列表
     *
     * @param page 当前页数
     * @param size 每页显示数量
     * @return com.baomidou.mybatisplus.core.metadata.IPage<com.hwd.gmall.model.product.BaseTrademark>
     */
    @Override
    public IPage<BaseTrademark> listBaseTrademarkPage(Long page, Long size) {
        return baseTrademarkMapper.selectPage(new Page<>(page, size), null);
    }

    /**
     * 根据品牌 id 查询品牌图片
     *
     * @param id 品牌id
     * @return com.hwd.gmall.model.product.BaseTrademark
     */
    @Override
    public BaseTrademark getBaseTrademarkById(Long id) {
        return baseTrademarkMapper.selectById(id);
    }

    /**
     * 保存/修改商标品牌
     *
     * @param baseTrademark 商标品牌
     */
    @Override
    public void saveOrUpdateBaseTrademark(BaseTrademark baseTrademark) {
        // 参数校验
        if (baseTrademark == null) {
            throw new RuntimeException("参数不能为空！");
        }

        // 判断id是否为空，为空新增，不为空修改
        if (baseTrademark.getId() == null) {
            // 新增商标品牌
            int insert = baseTrademarkMapper.insert(baseTrademark);
            if (insert <= 0) {
                throw new RuntimeException("新增商标品牌失败");
            }
        } else {
            // 修改商标品牌
            int update = baseTrademarkMapper.updateById(baseTrademark);
            if (update < 0) {
                throw new RuntimeException("修改商标品牌失败");
            }
        }

    }

    /**
     * 根据id删除商标品牌
     *
     * @param id 商标品牌id
     */
    @Override
    public void removeBaseTrademark(Long id) {
        int delete = baseTrademarkMapper.deleteById(id);
        if (delete < 0) {
            throw new RuntimeException("删除商标品牌失败");
        }
    }

    /**
     * 删除spu附属表信息
     *
     * @param spuInfo spu商品信息
     */
    private void deleteSpuExtraInfo(SpuInfo spuInfo) {
        // 删除图片
        int delete = spuImageMapper.delete(
                new LambdaQueryWrapper<SpuImage>()
                        .eq(SpuImage::getSpuId, spuInfo.getId()));
        // 删除销售属性表信息
        int delete1 = spuSaleAttrMapper.delete(
                new LambdaQueryWrapper<SpuSaleAttr>()
                        .eq(SpuSaleAttr::getSpuId, spuInfo.getId()));
        // 删除销售属性值表信息
        int delete2 = spuSaleAttrValueMapper.delete(
                new LambdaQueryWrapper<SpuSaleAttrValue>()
                        .eq(SpuSaleAttrValue::getSpuId, spuInfo.getId()));
        if (delete < 0 || delete1 < 0 || delete2 < 0) {
            throw new RuntimeException("修改spu失败");
        }
    }

    /**
     * 删除旧的附属表信息
     *
     * @param skuInfo 库存单位商品信息
     */
    private void deleteSkuExtraInfo(SkuInfo skuInfo) {

        // 删除sku的图片
        int delete = skuImageMapper.delete(
                new LambdaQueryWrapper<SkuImage>()
                        .eq(SkuImage::getSkuId, skuInfo.getId()));

        // 删除sku的平台属性
        int delete1 = skuAttrValueMapper.delete(
                new LambdaQueryWrapper<SkuAttrValue>()
                        .eq(SkuAttrValue::getSkuId, skuInfo.getId()));

        // 删除sku销售属性
        int delete2 = skuSaleAttrValueMapper.delete(
                new LambdaQueryWrapper<SkuSaleAttrValue>()
                        .eq(SkuSaleAttrValue::getSkuId, skuInfo.getId()));

        // 判断删除状态
        if (delete < 0 || delete1 < 0 || delete2 < 0) {
            throw new RuntimeException("修改sku失败");
        }
    }

    /**
     * 补全skuId后，新增sku销售属性
     *
     * @param skuSaleAttrValueList sku销售属性列表
     * @param skuId                库存单元id
     * @param spuId                商品表id
     */
    private void saveSkuSaleAttrValueList(List<SkuSaleAttrValue> skuSaleAttrValueList, Long skuId, Long spuId) {
        skuSaleAttrValueList.stream()
                .peek(skuSaleAttrValue -> {
                    skuSaleAttrValue.setSkuId(skuId);
                    skuSaleAttrValue.setSpuId(spuId);
                })
                .forEach(skuSaleAttrValue -> {
                    // 保存sku销售属性
                    int insert = skuSaleAttrValueMapper.insert(skuSaleAttrValue);
                    if (insert <= 0) {
                        throw new RuntimeException("操作sku失败");
                    }
                });
    }

    /**
     * 补全skuId后，新增sku的平台属性
     *
     * @param skuAttrValueList 平台属性列表
     * @param skuId            库存单元id
     */
    private void saveSkuAttrValueList(List<SkuAttrValue> skuAttrValueList, Long skuId) {
        skuAttrValueList.stream()
                .peek(skuAttrValue -> skuAttrValue.setSkuId(skuId))
                .forEach(skuAttrValue -> {
                    // 保存sku的平台属性
                    int insert = skuAttrValueMapper.insert(skuAttrValue);
                    if (insert <= 0) {
                        throw new RuntimeException("操作sku失败");
                    }
                });
    }

    /**
     * 补全skuId后，新增sku的图片
     *
     * @param skuImageList sku图片列表
     * @param skuId        库存单元id
     */
    private void saveSkuImageList(List<SkuImage> skuImageList, Long skuId) {
        skuImageList.stream()
                .peek(skuImage -> skuImage.setSkuId(skuId))
                .forEach(skuImage -> {
                    // 保存图片
                    int insert = skuImageMapper.insert(skuImage);
                    if (insert <= 0) {
                        throw new RuntimeException("操作sku失败");
                    }
                });
    }

    /**
     * 新增销售属性和值表
     *
     * @param spuSaleAttrList 销售属性和值列表
     * @param spuInfoId       spu商品id
     */
    private void saveSpuSaleAttrList(List<SpuSaleAttr> spuSaleAttrList, Long spuInfoId) {
        spuSaleAttrList.stream()
                .peek(spuSaleAttr -> spuSaleAttr.setSpuId(spuInfoId))
                .forEach(spuSaleAttr -> {
                    // 保存销售属性
                    int insert = spuSaleAttrMapper.insert(spuSaleAttr);
                    if (insert <= 0) {
                        throw new RuntimeException("操作spu失败");
                    }
                    // 保存销售属性值的信息
                    saveSpuSaleAttrValueList(spuInfoId, spuSaleAttr.getSpuSaleAttrValueList(), spuSaleAttr.getSaleAttrName());
                });
    }

    /**
     * 保存销售属性值的信息
     *
     * @param spuInfoId            销售属性id
     * @param spuSaleAttrValueList 销售属性值列表
     * @param saleAttrName         销售属性名称
     */
    private void saveSpuSaleAttrValueList(Long spuInfoId, List<SpuSaleAttrValue> spuSaleAttrValueList, String saleAttrName) {
        spuSaleAttrValueList.stream()
                .peek(spuSaleAttrValue -> {
                    spuSaleAttrValue.setSpuId(spuInfoId);
                    spuSaleAttrValue.setSaleAttrName(saleAttrName);
                })
                .forEach(spuSaleAttrValue -> {
                    int insert = spuSaleAttrValueMapper.insert(spuSaleAttrValue);
                    if (insert <= 0) {
                        throw new RuntimeException("操作spu失败");
                    }
                });
    }

    /**
     * 保存spu商品图片
     *
     * @param spuImageList spu商品图片列表
     * @param spuInfoId    spu商品id
     */
    private void saveSpuImageList(List<SpuImage> spuImageList, Long spuInfoId) {
        spuImageList.stream()
                .peek(spuImage -> spuImage.setSpuId(spuInfoId))
                .forEach(spuImage -> {
                    //保存spu商品图片
                    int insert = spuImageMapper.insert(spuImage);
                    if (insert <= 0) {
                        throw new RuntimeException("操作spu失败");
                    }
                });
    }
}
